/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.progin.drop.core;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author HP
 */
public class MessageOperator {
    private Message mTargetMessage = null;
    private OverflowHandler mHandler = null;
    public long mAttachmentLength = 0;

    public MessageOperator() {
        mTargetMessage = null;
    }

    public void setHandler(OverflowHandler handler) {
        mHandler = handler;
    }

    public MessageOperator(Message targetMessage) {
        mTargetMessage = targetMessage;
    }

    public void setTargetMessage(Message m) {
        mTargetMessage = m;
    }

    public void send(Socket sock) throws MessageException {
        
        DataOutputStream out = null;
        try {
            int id = Integer.valueOf(mTargetMessage.getId());
            out = new DataOutputStream(sock.getOutputStream());

            //int length = (mTargetMessage.getByteStream() == null) ? mTargetMessage.toString().length() : mTargetMessage.toString().length() + mTargetMessage.getByteStream().length;
            long length = mTargetMessage.toString().length() + mTargetMessage.getAttachmentLength();

            out.writeLong(length);
            //System.out.println("Sending message with length : " + mTargetMessage.toString().length());
            System.out.println("SENDING MESSAGE : " + mTargetMessage);
            out.write(mTargetMessage.toString().getBytes());
            //byte[] stream = mTargetMessage.getByteStream();
            /*if (mTargetMessage.getByteStream() != null) {
                //System.out.println(mTargetMessage.getByteStream().length);
                for (int i = 0 ; i < stream.length ; i++) {
                    //out.write(stream, 0, 1);
                    //out.flush();
                    //System.out.println(i);
                }
                //out.write(stream);
            }*/

            if (mTargetMessage.getAttachmentLength() != 0) {
                FileInputStream fis = new FileInputStream(mTargetMessage.getAttachment());

                byte[] b = new byte[1024 * 1024];
                int i = 0;
                while (i < mTargetMessage.getAttachmentLength()) {
                    if (fis.available() >= 1024 * 1024) {
                        fis.read(b);
                        i += 1024 * 1024;
                    }
                    else {
                        b = new byte[fis.available()];
                        fis.read(b);
                        i += b.length;
                    }

                    out.write(b);
                }

                fis.close();
            }

            //System.out.println("SENDING COMPLETE");
            //out.close();
        } catch (IOException ex) {
            Logger.getLogger(MessageOperator.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
            //throw new MessageException("Message sending failed");
        } catch (MessageException ex) {
            throw new MessageException("Message sending failed");
        }
        
    }


    public Message getTargetMessage() {
        return mTargetMessage;
    }


    public void loadAttachment(Socket sock) {
        if (mAttachmentLength != 0 && mHandler != null) {
            DataInputStream in;
            try {
                in = new DataInputStream(sock.getInputStream());
                int i = 0;
                //System.out.println("OK");
                byte[] bytes = new byte[1024 * 1024];
                mHandler.beforeSave();
                //bytes = new byte[length - i];
                while (i < mAttachmentLength) {
                    //byte b = in.readByte();
                    int count = in.read(bytes);
                    //System.out.println(count);
                    mHandler.save(bytes , count);
                    i += count;
                }
                mHandler.afterSave();
                //retval = Message.construct(stream , mHandler.getTargetFile());
                mTargetMessage.setAttachment(mHandler.getTargetFile());
            } catch (IOException ex) {
                mHandler.recoverError();
                Logger.getLogger(MessageOperator.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public Message receive(Socket sock) throws MessageException {
        Message retval = null;
        try {
            DataInputStream in = new DataInputStream(sock.getInputStream());

            //while (in.available() == 0) {}

            long length = in.readLong();

            System.out.println("Message length : " + length);

            String stream = "";
            int i = 0;
            int separatorCount = 0;
            while (separatorCount < 3) {
                char c;
                c = (char) in.read();
                stream += c;

                if (c == '#')
                    separatorCount++;

                i++;
            }

            retval = Message.construct(stream);
            if (i < length) {
                mAttachmentLength = length - i;
            }
            /*if (i < length && mHandler != null) {
                System.out.println("OK");
                byte[] bytes = new byte[1024 * 1024];
                mHandler.beforeSave(retval);
                //bytes = new byte[length - i];
                while (i < length) {
                    //byte b = in.readByte();
                    int count = in.read(bytes);
                    System.out.println(count);
                    mHandler.save(bytes , count);
                    i += count;
                }
                mHandler.afterSave();
                //retval = Message.construct(stream , mHandler.getTargetFile());
                retval.setAttachment(mHandler.getTargetFile());
            }*/
            
            //in.close();
        } catch (IOException ex) {
            //Logger.getLogger(MessageOperator.class.getName()).log(Level.SEVERE, null, ex);
            throw new MessageException("Message receiving failed");
        }

        mTargetMessage = retval;
        return retval;
    }
}
